package cn.stylefeng.guns.modular.demo.controller;


import cn.stylefeng.guns.core.exception.BusinessException;
import cn.stylefeng.guns.core.exception.BusinessExceptionEnum;
import cn.stylefeng.guns.dao.IGoodsService;
import cn.stylefeng.guns.dao.IRuleService;
import cn.stylefeng.guns.dao.IRuleSupplierService;
import cn.stylefeng.guns.dao.ISupplierService;
import cn.stylefeng.guns.dao.entity.Goods;
import cn.stylefeng.guns.dao.entity.Rule;
import cn.stylefeng.guns.dao.entity.RuleSupplier;
import cn.stylefeng.guns.dao.entity.Supplier;
import cn.stylefeng.guns.modular.demo.controller.convert.RuleConverter;
import cn.stylefeng.guns.modular.demo.controller.domain.*;
import cn.stylefeng.guns.modular.demo.excel.domain.PurchaseExcelData;
import cn.stylefeng.guns.modular.demo.excel.listener.PurchasePlanListener;
import cn.stylefeng.guns.modular.demo.service.ReportService;
import cn.stylefeng.guns.modular.demo.service.RuleBizService;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.annotation.BusinessLog;
import cn.stylefeng.roses.kernel.rule.enums.ResBizTypeEnum;
import cn.stylefeng.roses.kernel.rule.pojo.response.ResponseData;
import cn.stylefeng.roses.kernel.rule.pojo.response.SuccessResponseData;
import cn.stylefeng.roses.kernel.scanner.api.annotation.ApiResource;
import cn.stylefeng.roses.kernel.scanner.api.annotation.GetResource;
import cn.stylefeng.roses.kernel.scanner.api.annotation.PostResource;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@Slf4j
@ApiResource(name = "规则", resBizType = ResBizTypeEnum.BUSINESS, path = "/rule")
public class RuleController {

    @Resource
    private IRuleService ruleService;
    @Resource
    private RuleBizService ruleBizService;
    @Resource
    private IRuleSupplierService ruleSupplierService;
    @Resource
    private ISupplierService supplierService;
    @Resource
    private ReportService reportService;
    @Resource
    private RuleConverter ruleConverter;
    @Resource
    private IGoodsService goodsService;

    /**
     * 示例方法
     *
     * @author fengshuonan
     * @since 2021/1/24 10:59
     */
    @PostResource(name = "规则列表", path = "/list", requiredLogin = true, requiredPermission = true)
    @ApiOperation("查询规则列表")
    public ResponseData<PageResult<Rule>> list(@RequestBody QueryRuleRequest queryRuleRequest) {

        Page<Rule> page = new Page<>();
        page.setCurrent(queryRuleRequest.getPageNo());
        page.setSize(queryRuleRequest.getPageSize());
        LambdaQueryWrapper<Rule> lambdaQueryWrapper = Wrappers.<Rule>lambdaQuery().eq(Objects.nonNull(queryRuleRequest.getPublicStatus()), Rule::getPublicStatus, queryRuleRequest.getPublicStatus()).eq(!StringUtils.isEmpty(queryRuleRequest.getRuleId()), Rule::getRuleId, queryRuleRequest.getRuleId());
        Page<Rule> page1 = ruleService.page(page, lambdaQueryWrapper);
        return new SuccessResponseData<>(PageResultFactory.createPageResult(page1));
    }


    @ResponseBody
    @PostResource(name = "规则删除", path = "/delete", requiredLogin = true, requiredPermission = true)
    @ApiOperation("规则删除")
    @BusinessLog
    public ResponseData<Boolean> delete(String id) throws IOException {
        ruleBizService.deleteRule(id);
        return new SuccessResponseData<>(true);
    }

    @ResponseBody
    @PostResource(name = "规则保存或者修改", path = "/save", requiredLogin = true, requiredPermission = true)
    @ApiOperation("规则保存或者修改")
    @BusinessLog
    public ResponseData<Boolean> save(@RequestBody SaveRuleRequest request) throws IOException {
        ruleBizService.saveRule(request);
        return new SuccessResponseData<>(true);
    }

    @ResponseBody
    @GetResource(name = "规则详情", path = "/detail", requiredLogin = true, requiredPermission = true)
    @ApiOperation("规则详情")
    public ResponseData<RuleVO> detail(String id) throws IOException {
        return new SuccessResponseData<>(ruleBizService.getDetail(id));
    }


    @ResponseBody
    @PostResource(name = "规则发布", path = "/publish", requiredLogin = true, requiredPermission = true)
    @ApiOperation("发布")
    @BusinessLog
    public ResponseData<Boolean> publish(String id) throws IOException {
        Rule byId = ruleService.getById(id);
        byId.setPublicStatus(1);
        byId.setPublicTime(System.currentTimeMillis());
        ruleService.updateById(byId);
        return new SuccessResponseData<>(true);
    }


    @PostResource(name = "关联列表", path = "/correlation/list", requiredLogin = true, requiredPermission = true)
    @ApiOperation("规则关联列表")
    public ResponseData<PageResult> listCorrelation(@RequestBody QuerySupplierRuleRequest queryRuleRequest) {

        Page page = new Page<>();
        page.setCurrent(queryRuleRequest.getPageNo());
        page.setSize(queryRuleRequest.getPageSize());
        LambdaQueryWrapper<RuleSupplier> lambdaQueryWrapper = Wrappers.<RuleSupplier>lambdaQuery()
                .eq(!StringUtils.isEmpty(queryRuleRequest.getGoodsId()), RuleSupplier::getGoodsId, queryRuleRequest.getGoodsId())
                .eq(!StringUtils.isEmpty(queryRuleRequest.getSupplierId()), RuleSupplier::getSupplierId, queryRuleRequest.getSupplierId())
                .eq(!StringUtils.isEmpty(queryRuleRequest.getRuleId()), RuleSupplier::getRuleId, queryRuleRequest.getRuleId());
        page = ruleSupplierService.page(page, lambdaQueryWrapper);

        List<RuleSupplier> records = page.getRecords();
        if (CollectionUtils.isNotEmpty(records)) {
            List<String> supplierIdList = records.stream().map(RuleSupplier::getSupplierId).collect(Collectors.toList());
            List<String> ruleIdList = records.stream().map(RuleSupplier::getRuleId).collect(Collectors.toList());
            List<String> goodsId = records.stream().map(RuleSupplier::getGoodsId).collect(Collectors.toList());

            Map<String, Supplier> supplierMap = supplierService.listByIds(supplierIdList).stream().collect(Collectors.toMap(Supplier::getSupplierId, Function.identity()));
            Map<String, Rule> ruleMap = ruleService.listByIds(ruleIdList).stream().collect(Collectors.toMap(Rule::getRuleId, Function.identity()));
            Map<String, Goods> goodsMap = goodsService.listByIds(goodsId).stream().collect(Collectors.toMap(Goods::getGoodsId, Function.identity()));


            List<RuleSupplierVO> collect = records.stream().map(r -> {
                RuleSupplierVO ruleSupplierVO = ruleConverter.do2vo(r);
                ruleSupplierVO.setRuleName(Optional.ofNullable(ruleMap.get(r.getRuleId())).map(Rule::getName).orElse(""));
                ruleSupplierVO.setSupplierName(Optional.ofNullable(supplierMap.get(r.getSupplierId())).map(Supplier::getName).orElse(""));
                ruleSupplierVO.setSupplierCode(Optional.ofNullable(supplierMap.get(r.getSupplierId())).map(Supplier::getSupplierCode).orElse(""));
                ruleSupplierVO.setCommodityName(Optional.ofNullable(goodsMap.get(r.getGoodsId())).map(Goods::getCommodityName).orElse(""));
                ruleSupplierVO.setCommodityCode(Optional.ofNullable(goodsMap.get(r.getGoodsId())).map(Goods::getCommodityCode).orElse(""));
                return ruleSupplierVO;
            }).collect(Collectors.toList());
            page.setRecords(collect);
        }
        return new SuccessResponseData<>(PageResultFactory.createPageResult(page));
    }


//    @ResponseBody
//    @PostResource(name = "二次确认 是否弹框，true弹 false不弹", path = "/confirmation", requiredLogin = false, requiredPermission = false)
//    @ApiOperation("是否弹框")
//    public ResponseData<Boolean> secondaryConfirmation(@RequestBody CorrelationRequest request) throws IOException {
//
//        long count = ruleSupplierService.count(Wrappers.<RuleSupplier>lambdaQuery().eq(RuleSupplier::getCommodityCode, request.getCommodityCode()).eq(RuleSupplier::getRuleId, request.getRuleId()).eq(RuleSupplier::getSupplierId, request.getSupplierId()).eq(RuleSupplier::getEffectiveStatus, EffectiveStatusEnum.ING.getEffectiveStatus()));
//        //有生效中的需要二次确认下
//        return new SuccessResponseData<>(count > 0);
//    }

    @ResponseBody
    @PostResource(name = "关联", path = "/correlation", requiredLogin = true, requiredPermission = true)
    @ApiOperation("关联")
    @BusinessLog
    public ResponseData<Boolean> correlation(@RequestBody CorrelationRequest request) throws IOException {
        //5.24 变更 政策可以叠加
//        Boolean exist = ruleSupplierService.isExist(request.getSupplierIds(), request.getGoodsId(), request.getStartTime(), request.getEndTime());
        //有未生效的不能再保存
//        if (exist) {
//            throw new BusinessException(BusinessExceptionEnum.BUSINESS_DATA_REPEAT, "供应商、单品、政策已存在同一时间的应用关系，不能添加");
//        }
        List<RuleSupplier> collect = request.getSupplierIds().stream().map(r -> {
            RuleSupplier ruleSupplier = new RuleSupplier();
            ruleSupplier.setRuleId(request.getRuleId());
            ruleSupplier.setGoodsId(request.getGoodsId());
            ruleSupplier.setSupplierId(r);
            ruleSupplier.setEffectiveTime(request.getStartTime());
            ruleSupplier.setEffectiveEndTime(request.getEndTime());
            return ruleSupplier;
        }).collect(Collectors.toList());
        ruleSupplierService.saveBatch(collect);
        return new SuccessResponseData<>(true);
    }




    @ResponseBody
    @PostResource(name = "规则撤销", path = "/cancel", requiredLogin = true, requiredPermission = true)
    @ApiOperation("规则撤销")
    @BusinessLog
    public ResponseData<Boolean> cancel(String id) throws IOException {
        ruleBizService.deleteRule(id);
        return new SuccessResponseData<>(true);
    }


//    @ResponseBody
//    @PostResource(name = "生成报表", path = "/report", requiredLogin = false, requiredPermission = false)
//    @ApiOperation("生成报表")
//    @BusinessLog
//    public ResponseData<Boolean> report(HttpServletResponse response) throws IOException {
//
//        response.setHeader("Content-Disposition", "attachment;filename=" + "返利报表.xlsx");
//        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//        response.setCharacterEncoding("utf-8");
//
//        try {
//            reportService.generate(response.getOutputStream());
//        } catch (Exception e) {
//            e.printStackTrace();
//            log.info("导出错误", e);
//            // 重置response
//            response.reset();
//            response.setContentType("application/json");
//            response.setCharacterEncoding("utf-8");
////            Map<String, String> map = MapUtils.newHashMap();
////            map.put("status", "failure");
////            map.put("message", "下载文件失败" + e.getMessage());
////            response.getWriter().println(JSON.toJSONString(map));
//
//            return new SuccessResponseData<>(false);
//        }
//        return new SuccessResponseData<>(true);
//    }

//    @ResponseBody
//    @PostResource(name = "生成年报报表", path = "/reportYeah", requiredLogin = false, requiredPermission = false)
//    @ApiOperation("生成报表")
//    @BusinessLog
//    public ResponseData<Boolean> reportYear(HttpServletResponse response) throws IOException {
//
//        response.setHeader("Content-Disposition", "attachment;filename=" + "返利报表.xlsx");
//        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//        response.setCharacterEncoding("utf-8");
//
//        try {
//            reportService.generateYear(response.getOutputStream());
//        } catch (Exception e) {
//            e.printStackTrace();
//            log.info("导出错误", e);
//            // 重置response
//            response.reset();
//            response.setContentType("application/json");
//            response.setCharacterEncoding("utf-8");
////            Map<String, String> map = MapUtils.newHashMap();
////            map.put("status", "failure");
////            map.put("message", "下载文件失败" + e.getMessage());
////            response.getWriter().println(JSON.toJSONString(map));
//
//            return new SuccessResponseData<>(false);
//        }
//        return new SuccessResponseData<>(true);
//    }

    @ResponseBody
    @PostResource(name = "采购计划生成", path = "/plan", requiredLogin = false, requiredPermission = false)
    @ApiOperation("采购计划生成")
    @BusinessLog
    public ResponseData<String> upload(MultipartFile file, HttpServletResponse response) throws IOException {
        response.setHeader("Content-Disposition", "attachment;filename=" + "plan.xlsx");
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), PurchaseExcelData.class).build()) {
            WriteSheet writeSheetYeah = EasyExcel.writerSheet("data").build();
            List<PurchaseExcelData> dataList = Lists.newArrayList();
            EasyExcel.read(file.getInputStream(), PurchaseExcelData.class, new PurchasePlanListener(dataList)).sheet().doRead();
            excelWriter.write(dataList, writeSheetYeah);
        }

        return new SuccessResponseData<>();
    }


    @ResponseBody
    @PostResource(name = "删除关联", path = "/correlation/delete", requiredLogin = true, requiredPermission = true)
    @ApiOperation("删除关联")
    @BusinessLog
    public ResponseData<Boolean> deleteCorrelation(String id) throws IOException {
        RuleSupplier byId = ruleSupplierService.getById(id);
        if (Objects.isNull(byId)) {
            throw new BusinessException(BusinessExceptionEnum.BUSINESS_DATA_NOT_EXITS);
        }
        ruleSupplierService.removeById(id);
        return new SuccessResponseData<>(true);
    }


}
